//
//  HTTool.swift
//  MagaCore
//
//  Created by MrMessy on 2023/5/29.
//

import Foundation
import Zip
import MediaPlayer
import CoreTelephony

struct HTTools {
  // 获取app唯一id
  static func ht_getBundleID() -> String {
    if let var_bundleIdentifier = Bundle.main.bundleIdentifier {
      return var_bundleIdentifier
    }
    return "96"
  }

  // 获取app版本号
  static func ht_getAppVersion() -> String {
    if let var_appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String {
      return var_appVersion
    } else {
      return ""
    }
  }

  // 获取设备identifierForVendor
  static func ht_getDeviceIdentifier() -> String {
    if let var_identifier = UIDevice.current.identifierForVendor?.uuidString {
      return var_identifier
    } else {
      return ""
    }
  }

  // 获取屏幕分辨率
  static func ht_getScreenResolution() -> String {
    let var_screenSize = UIScreen.main.bounds.size
    let var_resolution = "\(Int(var_screenSize.width)) x \(Int(var_screenSize.height))"
    return var_resolution
  }

  // 获取国家语言
  static func ht_getDeviceLocale() -> (var_country: String?, var_language: String?) {
    let var_currentLocale = Locale.current
    let var_country = var_currentLocale.regionCode
    let var_language = var_currentLocale.languageCode

    return (var_country, var_language)
  }

  // 获取内存信息
  static func ht_getSystemMemory() -> (totalMemory: UInt64, freeMemory: UInt64)? {
    var var_info = mach_task_basic_info()
    var var_count = mach_msg_type_number_t(MemoryLayout<mach_task_basic_info>.size) / 4

    let var_result = withUnsafeMutablePointer(to: &var_info) {
      $0.withMemoryRebound(to: integer_t.self, capacity: Int(var_count)) {
        task_info(mach_task_self_, task_flavor_t(MACH_TASK_BASIC_INFO), $0, &var_count)
      }
    }

    guard var_result == KERN_SUCCESS else {
      return nil
    }

    let var_totalMemory = ProcessInfo.processInfo.physicalMemory
    let var_usedMemory = var_info.resident_size
    let var_freeMemory = var_totalMemory - UInt64(var_usedMemory)
    return (totalMemory: var_totalMemory, freeMemory: var_freeMemory)
  }

  // 获取剩余存储
  static func ht_getFreeDiskSpace() -> UInt64 {
    do {
      let var_fileURL = URL(fileURLWithPath: NSHomeDirectory())
      let var_systemAttributes = try FileManager.default.attributesOfFileSystem(forPath: var_fileURL.path)
      if let var_freeSize = var_systemAttributes[.systemFreeSize] as? NSNumber {
        return var_freeSize.uint64Value
      }
    } catch {
      print("Error: \(error)")
      return 0
    }

    return 0
  }

  // 获取系统音量大小
  static func getSystemVolumValue() -> Float {
    do{
      try AVAudioSession.sharedInstance().setActive(true)
    }catch let error as NSError{
      print("\(error)")
    }
    let var_currentVolume = AVAudioSession.sharedInstance().outputVolume
    return var_currentVolume
  }

  // 获取IMSI
  static func ht_getImsi() -> String {
    let var_networkInfo = CTTelephonyNetworkInfo()
    var var_imsi: String = ""
    if let carrierProviders = var_networkInfo.serviceSubscriberCellularProviders {
      for item in carrierProviders.values {
        if var_imsi != "" {
          break
        }
        var_imsi = "\(item.mobileCountryCode ?? "")\(item.mobileNetworkCode ?? "")"
      }
    }
    return var_imsi
  }

  // 判断是否插入手机卡
  static func ht_getSimCardStatus() -> String {
    let var_networkInfo = CTTelephonyNetworkInfo()
    if let carrierProviders = var_networkInfo.serviceSubscriberCellularProviders {
      for item in carrierProviders.values {
        if item.mobileNetworkCode != nil {
          return "1"
        }
      }
    }

    return "0"
  }

  // 调节系统音量大小
  static func setSysVolum(_ value: Float) {
    let var_volumeView = MPVolumeView()
    if let var_view = var_volumeView.subviews.first as? UISlider {
      DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {//延迟0.01秒就能够正常播放
        var_view.value = value
      }
    }
  }

  // 获取设备当前语言
  static func ht_getCurrentLanguage() -> String {
    let var_currentLocale = Locale.current
    let var_currentLanguage = var_currentLocale.languageCode

    if let var_languageCode = var_currentLanguage {
      return "\(var_languageCode)"
    } else {
      return "en"
    }
  }

  // 获取时区
  static func ht_getTimeZone() -> String {
    let var_currentTimeZone = TimeZone.current
    let var_timeZoneIdentifier = var_currentTimeZone.identifier

    return "\(var_timeZoneIdentifier)"
  }

  // 更改屏幕旋转方向
  static func ht_updateInterfaceOrientations(orientation: UIDeviceOrientation = .portrait) {
    // 控制横竖屏
    if #available(iOS 16.0, *) {
      var var_orient = UIInterfaceOrientationMask.portrait
      if orientation == .landscapeLeft || orientation == .landscapeRight {
        var_orient = UIInterfaceOrientationMask.landscape
      }
      // `iOS16`由于不能再设置`UIDevice.orientation`来控制横竖屏了，所以`UIDeviceOrientationDidChangeNotification`将由系统自动发出，
      // 即手机的摆动就会自动收到通知，不能自己控制，因此不能监听该通知来适配UI，
      // 重写`UIViewController`的`-viewWillTransitionToSize:withTransitionCoordinator:`方法来监听屏幕的旋转并适配UI。
      let geometryPreferences = UIWindowScene.GeometryPreferences.iOS(interfaceOrientations: var_orient)
      for scene in UIApplication.shared.connectedScenes {
        guard let windowScene = scene as? UIWindowScene else { continue }
        // 一般来说app只有一个`windowScene`，而`windowScene`内可能有多个`window`，
        // 例如Demo中至少有两个`window`：第一个是app主体的`window`，第二个则是`FunnyButton`所在的`window`，
        // 所以需要遍历全部`window`进行旋转，保证全部`window`都能保持一致的屏幕方向。

        // `iOS16`之后`attemptRotationToDeviceOrientation`建议不再使用（虽然还起效），
        // 而是调用`setNeedsUpdateOfSupportedInterfaceOrientations`进行屏幕旋转。
        for window in windowScene.windows {
          guard let rootViewController = window.rootViewController else { continue }
          // 由于Demo中只用到`rootViewController`控制屏幕方向，所以只对`rootViewController`调用即可。
          rootViewController.setNeedsUpdateOfSupportedInterfaceOrientations()
          // 若需要全部控制器都执行`setNeedsUpdateOfSupportedInterfaceOrientations`，可调用该函数：
          // Self.setNeedsUpdateOfSupportedInterfaceOrientations(rootViewController, nil)
        }

        //【注意】要在全部`window`调用`requestGeometryUpdate`之前，先对`vc`调用`attemptRotationToDeviceOrientation`，
        // 否则会报错（虽然对屏幕旋转没影响）。
        for window in windowScene.windows {
          window.windowScene?.requestGeometryUpdate(geometryPreferences)
        }
      }

      UIViewController.attemptRotationToDeviceOrientation()
    } else {
      // `iOS16`之前调用`attemptRotationToDeviceOrientation`屏幕才会旋转。
      //【注意】要在确定改变的方向【设置之后】才调用，否则会旋转到【设置之前】的方向
      UIViewController.attemptRotationToDeviceOrientation()

      // `iOS16`之前修改"orientation"后会直接影响`UIDevice.currentDevice.orientation`；
      // `iOS16`之后不能再通过设置`UIDevice.orientation`来控制横竖屏了，修改"orientation"无效。
      UIDevice.current.setValue(orientation.rawValue, forKeyPath: "orientation")
    }
  }

  // 解压缩文件
  static func ht_unzipFile(url: String, andSuccess: @escaping ([HTSubtitle]) -> Void, andFail: @escaping () -> Void) {
    guard let var_zipURL = URL(string: url) else {
      print("Invalid URL")
      andFail()
      return
    }

    let var_fileNameWithExtension = var_zipURL.lastPathComponent
    let var_fileName = (var_fileNameWithExtension as NSString).deletingPathExtension
    let var_unzipDestinationURL = FileManager.default.temporaryDirectory.appendingPathComponent("unzippedFile")
    let var_filePath = var_unzipDestinationURL.appendingPathComponent(var_fileName)

    let var_fileExists = ht_fileExistsInDirectory(filePath: var_filePath.absoluteString, directoryPath: var_unzipDestinationURL.absoluteString)
    if var_fileExists {
      print("\(var_filePath.lastPathComponent)已存在")
      let var_subtitles = ht_parseSRTFile(filePath: var_filePath.absoluteString.replacingOccurrences(of: "file://", with: ""))
      andSuccess(var_subtitles)
    }

    let var_task = URLSession.shared.downloadTask(with: var_zipURL) { (tempLocalURL, response, error) in
      if let var_error = error {
        print("下载失败：\(var_error.localizedDescription)")
        andFail()
        return
      } else if let var_tempLocalURL = tempLocalURL {
        let var_documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let var_destinationURL = var_documentsDirectory.appendingPathComponent(var_zipURL.lastPathComponent)

        do {
          try FileManager.default.moveItem(at: var_tempLocalURL, to: var_destinationURL)

          try Zip.unzipFile(var_destinationURL, destination: var_unzipDestinationURL, overwrite: true, password: nil)
          print("解压完成: \(var_filePath)")
          let var_subtitles = ht_parseSRTFile(filePath: var_filePath.absoluteString.replacingOccurrences(of: "file://", with: ""))
          andSuccess(var_subtitles)
        } catch {
          print("解压失败：\(error.localizedDescription)")
          andFail()
        }
      }
    }

    var_task.resume()
  }

  static func ht_fileExistsInDirectory(filePath: String, directoryPath: String) -> Bool {
    let var_fileURL = URL(fileURLWithPath: filePath)
    let var_directoryURL = URL(fileURLWithPath: directoryPath)

    let var_fileInDirectoryURL = var_directoryURL.appendingPathComponent(var_fileURL.lastPathComponent)

    return FileManager.default.fileExists(atPath: var_fileInDirectoryURL.path)
  }

  static func ht_parseSRTFile(filePath: String) -> [HTSubtitle] {
    do {
      let var_srtContent = try String(contentsOfFile: filePath, encoding: .utf8)
      let var_HTSubtitleArray = var_srtContent.components(separatedBy: "\n\n")

      var var_HTSubtitles: [HTSubtitle] = []

      for var_HTSubtitleString in var_HTSubtitleArray {
        let var_HTSubtitle = ht_parseHTSubtitleString(HTSubtitleString: var_HTSubtitleString)
        var_HTSubtitles.append(var_HTSubtitle)
      }

      return var_HTSubtitles
    } catch {
      print("无法读取字幕文件：\(error)")
      return []
    }
  }

  static func ht_parseHTSubtitleString(HTSubtitleString: String) -> HTSubtitle {
    let var_lines = HTSubtitleString.split(separator: "\n", maxSplits: 2)

    if var_lines.count >= 3 {
      let var_id = Int(var_lines[0]) ?? 0
      let var_timeString = var_lines[1]
      let var_text = String(var_lines[2])

      let var_timeComponents = var_timeString.components(separatedBy: " --> ")
      if var_timeComponents.count == 2 {
        let var_startTime = ht_parseTime(timeString: var_timeComponents[0])
        let var_endTime = ht_parseTime(timeString: var_timeComponents[1])

        return HTSubtitle(var_id: var_id, var_startTime: var_startTime, var_endTime: var_endTime, var_text: var_text)
      }
    }

    return HTSubtitle(var_id: 0, var_startTime: 0, var_endTime: 0, var_text: "")
  }

  static func ht_parseTime(timeString: String) -> TimeInterval {
    let var_timeComponents = timeString.components(separatedBy: ":")

    if var_timeComponents.count == 3 {
      let var_hours = Double(var_timeComponents[0]) ?? 0.0
      let var_minutes = Double(var_timeComponents[1]) ?? 0.0
      let var_secondsAndMillis = var_timeComponents[2].components(separatedBy: ",")

      if var_secondsAndMillis.count == 2 {
        let var_seconds = Double(var_secondsAndMillis[0]) ?? 0.0
        let var_milliseconds = Double(var_secondsAndMillis[1]) ?? 0.0

        let var_totalSeconds = var_hours * 3600 + var_minutes * 60 + var_seconds + var_milliseconds / 1000
        return TimeInterval(var_totalSeconds)
      }
    }

    return 0.0
  }

  // 设置字幕偏好
  static func ht_setSubTitlePreference(var_lang: String) {
    UserDefaults.standard.set(var_lang, forKey: "string_subtitleLang")
  }
  // 获取字幕偏好
  static func ht_getSubTitlePreference() -> String {
    return UserDefaults.standard.string(forKey: "string_subtitleLang") ?? ""
  }
}
